package com.shanlitech.et.controller;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.shanlitech.et.bean.RetData;
import com.shanlitech.et.mapper.SpeechRecordMapper;
import com.shanlitech.et.model.SpeechRecord;
import com.shanlitech.et.utils.ByteUtils;
import com.shanlitech.et.utils.HttpClientUtils;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.OutputStream;
import java.net.URI;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

@Controller
public class TestController {
    private final Logger logger= LoggerFactory.getLogger(this.getClass());
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private SpeechRecordMapper speechRecordMapper;

    @RequestMapping("testInsert")
    @ResponseBody
    public void insert(SpeechRecord record) {
        logger.info("insert收到参数:" + record);
        speechRecordMapper.insertSelective(record);
    }

    @RequestMapping("testUpdate")
    @ResponseBody
    public void update(SpeechRecord record) {
        logger.info("update收到参数:" + record);
        if(record != null && record.getSpeech_id() != null) {
            SpeechRecord recordInDB = speechRecordMapper.selectByPrimaryKey(record.getSpeech_id());
            if(recordInDB != null) {
                record.setGid(recordInDB.getGid());
                record.setUid(recordInDB.getUid());
                record.setT_start(recordInDB.getT_start());
                record.setPayload(recordInDB.getPayload());
                record.setAg_id(recordInDB.getAg_id());
            } else {
                logger.error("update failed recordInDB by speech_id null");
            }
        } else {
            logger.error("update failed speech_id null");
            return;
        }
        if(record == null) {
            logger.error("update failed, no result by speech_id " + record.getSpeech_id());
            return;
        }
        Map<String, Object> map = Maps.newHashMap();
        map.put("speech_id", record.getSpeech_id());
        map.put("gid", record.getGid());
        map.put("uid", record.getUid());
        map.put("ag_id", record.getAg_id());
        map.put("t_start", record.getT_start());
        map.put("t_end", record.getT_end());
        map.put("payload", record.getPayload());
        map.put("speech_index", record.getSpeech_index());
        redisTemplate.opsForHash().putAll(record.getSpeech_id()+"", map);
        Gson gson = new Gson();
        redisTemplate.opsForZSet().add(record.getGid()+"", gson.toJson(record, SpeechRecord.class), record.getT_start());
        speechRecordMapper.updateByPrimaryKeySelective(record);
        return;
    }

    @RequestMapping("testFindByGid")
    @ResponseBody
    public Object findByGid(String gid, String time, String count) {
        logger.info("根据gid查询讲话记录" + gid);
        long start = System.currentTimeMillis();
        RetData ret = new RetData();
        if(!StringUtils.hasText(gid)) {
            ret.setRet(-1);
            ret.setMsg("gid为空");
            return ret;
        }
        if(!StringUtils.hasText(time)) {
            time = System.currentTimeMillis() + "";
        }
        if(!StringUtils.hasText(count)) {
            count = "3";
        }
        List<SpeechRecord> records = Lists.newArrayList();
        Set<Object> entries = redisTemplate.opsForZSet().reverseRangeByScore(gid, 0, Long.valueOf(time));
        if(entries == null || entries.size() == 0) {
            records = speechRecordMapper.findByGidAndtStartLess(Long.parseLong(gid), Long.parseLong(time), Integer.parseInt(count));
        } else {
            List<Object> list = entries.stream().limit(Long.valueOf(count)).collect(Collectors.toList());
            if(list == null || list.size() == 0) {
                records = speechRecordMapper.findByGidAndtStartLess(Long.parseLong(gid), Long.parseLong(time), Integer.parseInt(count));
            } else {
                logger.info("findByGid进入redis缓存, 集合大小:" + list.size());
                StringBuilder result = new StringBuilder("{\"ret\":200,\"data\":[");
                for(Object v : list) {
                    //Gson gson = new Gson();
                    //SpeechRecord record = gson.fromJson((String) v, SpeechRecord.class);
                    //records.add(record);
                    result.append(v).append(",");
                }
                result.deleteCharAt(result.length() - 1);
                result.append("]}");
                long end = System.currentTimeMillis();
                logger.info("查询gid " + gid + " 讲话记录结束, 耗时" + (end-start) + "ms");
                return result.toString();
            }
        }
        ret.setData(records);
        long end = System.currentTimeMillis();
        logger.info("查询gid " + gid + " 讲话记录结束, 耗时" + (end-start) + "ms");
        return ret;
    }

    @RequestMapping("testFindBySpeechId")
    @ResponseBody
    public Object findBySpeechId(String speechId, HttpServletResponse response) {
        logger.info("根据speechId查询讲话记录" + speechId);
        RetData ret = new RetData();
        if(!StringUtils.hasText(speechId)) {
            ret.setRet(-1);
            ret.setMsg("参数为空");
            return ret;
        }
        Map<Object, Object> map = redisTemplate.opsForHash().entries(speechId);
        String speech_index = (String)map.get("speech_index");
        if(!StringUtils.hasText(speech_index)) {
            SpeechRecord speechRecord = speechRecordMapper.selectByPrimaryKey(Long.parseLong(speechId));
            speech_index = speechRecord.getSpeech_index();
        }
        if(StringUtils.hasText(speech_index)) {
            //根据文件索引去下载文件
            BufferedReader in = null;
            try {
                HttpClient client = HttpClientUtils.createSSLClientDefault();
                HttpGet request = new HttpGet();
                request.setURI(new URI(speech_index));

                //设置参数
                HttpResponse httpResponse = client.execute(request);
                int code = httpResponse.getStatusLine().getStatusCode();
                if(code == HttpStatus.SC_OK) {
                    byte[] result = EntityUtils.toByteArray(httpResponse.getEntity());
                    logger.info("下载的文件路径" + speech_index + "\n下载的文件内容:" + ByteUtils.toHexString(result));
                    response.setContentType("application/octet-stream;charset=utf-8");
                    String filenamedisplay = speechId;
                    filenamedisplay = URLEncoder.encode(filenamedisplay, "UTF-8");
                    response.addHeader("Content-Disposition", "attachment;filename="
                            + filenamedisplay + ".hex");
                    OutputStream os= response.getOutputStream();
                    os.write(result);
                    os.flush();
                    os.close();
                } else {
                    ret.setRet(-3);
                    ret.setMsg("语音文件下载错误" + code);
                    return ret;
                }
            } catch (Exception e) {
                logger.error("下载语音文件错误, speechId=" + speechId, e);
                ret.setRet(-3);
                ret.setMsg("语音文件下载错误");
                return ret;
            }

            return ret;
        } else {
            ret.setRet(-2);
            ret.setMsg("没有该条记录，或该语音记录未完成");
            return ret;
        }
    }

    /**
     * findByGids实现就是循环gids调用Set<Object> ids = redisTemplate.opsForZSet().reverseRangeByScore(gid, 0, Long.valueOf(time))得到多个ids
     * 取并集得到新的集合再stream().limit();
     */
}
